package org.emet.service;

import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.emet.Constants;
import org.emet.dao.CarriageDao;
import org.emet.dao.CeremonyDao;
import org.emet.dao.ChargeRecordDao;
import org.emet.dao.ChargetItemDao;
import org.emet.dao.CremationHistDao;
import org.emet.dao.FreezerDao;
import org.emet.dao.HallRentDao;
import org.emet.dao.RegistrationDao;
import org.emet.dao.storage.ItemDao;
import org.emet.dao.storage.SaleHistDao;
import org.emet.entity.biz.Carriage;
import org.emet.entity.biz.Ceremony;
import org.emet.entity.biz.ChargeItem;
import org.emet.entity.biz.ChargeRecord;
import org.emet.entity.biz.CremationHist;
import org.emet.entity.biz.FreezerRent;
import org.emet.entity.biz.HallRent;
import org.emet.entity.biz.Registration;
import org.emet.entity.storage.Item;
import org.emet.entity.storage.SaleHist;
import org.emet.entity.storage.SaleItem;
import org.emet.jee.BusinessException;
import org.emet.jee.core.dao.Page;
import org.emet.service.dto.ChargeRecordCriteria;
import org.emet.service.dto.ChargeRecordListItem;
import org.emet.service.storage.SaleMananger;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mysql.jdbc.Driver;

@Service
@Transactional(rollbackFor = Exception.class)
@RemotingDestination
public class ChargeRecordService {
	private static Logger logger = LoggerFactory.getLogger(ChargeRecordService.class);
	@Autowired
	private ChargeRecordDao chargeRecordDao;
	@Autowired
	private ChargetItemDao chargetItemDao;
	@Autowired
	private SaleMananger saleMananger;
	@Autowired
	private ItemDao itemDao;
	@Autowired
	private SaleHistDao saleHistDao;
	@Autowired
	private CarriageDao carriageDao;
	@Autowired
	private CeremonyDao ceremonyDao;
	@Autowired
	private CremationHistDao cremationHistDao;
	@Autowired
	private FreezerDao freezerDao;
	@Autowired
	private HallRentDao hallRentDao;
	@Autowired
	private RegistrationDao registrationDao;

	public List<ChargeItem> getUnpaiedItems(String bizNo) {
		List<Carriage> carriageList = carriageDao.findUnpaiedByBiz(bizNo);
		List<Ceremony> ceremonyList = ceremonyDao.findUnpaiedByBiz(bizNo);
		List<CremationHist> cremationHistList = cremationHistDao.findUnpaiedByBiz(bizNo);
		List<FreezerRent> freezerRentList = freezerDao.findUnpaiedByBiz(bizNo);
		List<HallRent> hallRentList = hallRentDao.findUnpaiedByBiz(bizNo);

		int length = carriageList.size() + ceremonyList.size() + cremationHistList.size() + freezerRentList.size()
				+ hallRentList.size();
		if (length > 0) {
			int i = 0;
			List<ChargeItem> result = new ArrayList<ChargeItem>(length);
			for (Carriage c : carriageList) {
				ChargeItem item = new ChargeItem();
				item.setCode(c.getBizNo() + i++);
				item.setCount(1);
				// item.setTotalFee(c.getFee());
				item.setDetailName("接运费");
				item.setType(Constants.CARRIAGE);
				item.setChargeId(c.getId());
				result.add(item);
			}
			for (Ceremony c : ceremonyList) {
				ChargeItem item = new ChargeItem();
				item.setCode(c.getReg().getBizNo() + i++);
				item.setCount(1);
				// item.setTotalFee(c.getFee());
				item.setDetailName("礼仪费");
				item.setType(Constants.CEREMONY);
				item.setChargeId(c.getId());
				result.add(item);
			}
			for (CremationHist c : cremationHistList) {
				ChargeItem item = new ChargeItem();
				item.setCode(c.getRegistration().getBizNo() + i++);
				item.setCount(1);
				// item.setTotalFee(c.getFee());
				item.setDetailName("火化费");
				item.setType(Constants.CREMATION_HIST);
				item.setChargeId(c.getId());
				result.add(item);
			}
			for (FreezerRent c : freezerRentList) {
				ChargeItem item = new ChargeItem();
				// item.setCode(c.getRegistration().getBizNo() + i++);
				item.setCount(1);
				// item.setTotalFee(c.getTotalFee());
				item.setDetailName("冷藏费");
				item.setType(Constants.FREEZER_RENT);
				item.setChargeId(c.getId());
				result.add(item);
			}
			for (HallRent c : hallRentList) {
				ChargeItem item = new ChargeItem();
				item.setCode(c.getRegistration().getBizNo() + i++);
				item.setCount(1);
				// item.setTotalFee(c.getTotalCharge());
				item.setDetailName("灵堂租赁费");
				item.setType(Constants.HALL_RENT);
				item.setChargeId(c.getId());
				result.add(item);
			}

			return result;
		}
		return null;
	}

	public void deleteChargeItem(Long... ids) {
		try {
			chargetItemDao.delete_batch(ids);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("发生异常!");
		}
	}

	public Long save(ChargeRecord entity) {
		Transaction tx = chargeRecordDao.getSession().beginTransaction();
		try {
			String bizNo = null;
			boolean isNew = false;

			markServicePaied(entity.getItems());

			//get reg from session
			if (entity.getRegistration() != null) {
				Long regId = entity.getRegistration().getId();
				Registration reg = registrationDao.get(regId);
				entity.setRegistration(reg);
			}

			if (entity.getId() == null) {
				isNew = true;
				chargeRecordDao.save(entity);
			} else if (entity.getId() != null) {
				//eidt
				//remove all old charge items.
				ChargeRecord entityInDB = chargeRecordDao.get(entity.getId());
				BeanUtils.copyProperties(entity, entityInDB, new String[] { "registration", "items" });
				Iterator<ChargeItem> it = entityInDB.getItems().iterator();
				while (it.hasNext()) {
					chargetItemDao.delete(it.next());
				}
				List<ChargeItem> items = entity.getItems();
				for (ChargeItem chargeItem : items) {
					chargeItem.setChargeRecord(entityInDB);
				}
				entityInDB.setItems(items);
				bizNo = entityInDB.getRegistration().getBizNo();
				//below is update operation for storage
				// 删除对应的进销存数据
				if (!isNew) {
					String oldFlowNo = entity.getId() + "-" + bizNo;
					deleteStorageHistRecord(oldFlowNo);
				}

				//				chargeRecordDao.save(entityInDB);

			}

			// 添加进销存数据
			Registration reg = entity.getRegistration();
			String flowNo = entity.getId() + "-" + reg.getBizNo();
			SaleHist storageHist = new SaleHist();
			storageHist.setFlowNo(flowNo);
			storageHist.setCustomer(reg.getClient());
			storageHist.setDate(entity.getChargeDate());
			storageHist.setOperatorName(entity.getOperator());
			storageHist.setItems(new ArrayList<SaleItem>());
			List<ChargeItem> items = entity.getItems();
			for (ChargeItem chargeItem : items) {
				if (chargeItem.getType().equalsIgnoreCase("I")) {
					SaleItem saleItem = new SaleItem();
					saleItem.setAmount(new BigDecimal((double) chargeItem.getCount() * chargeItem.getSingleFee()));
					saleItem.setDate(entity.getChargeDate());
					Item item = itemDao.findUniqueBy("name", chargeItem.getDetailName());
					saleItem.setItem(item);
					saleItem.setItemCount(chargeItem.getCount());
					saleItem.setSinglePrice(new BigDecimal(chargeItem.getSingleFee()));
					saleItem.setSaleHist(storageHist);
					storageHist.getItems().add(saleItem);
				}
			}
			if (storageHist.getItems().size() != 0) {
				saleMananger.saveOrUpdateSale(storageHist);
			}

			tx.commit();
			storageHist = null;
		} catch (Exception e) {
			tx.rollback();
			logger.error(e.getMessage(), e);
			throw new BusinessException(e.getMessage());
		}

		return entity.getId();
	}

	private void markServicePaied(List<ChargeItem> items) {
		Iterator<ChargeItem> it = items.iterator();
		while (it.hasNext()) {
			ChargeItem item = it.next();
			String type = item.getType();
			if (type.equals(Constants.CARRIAGE)) {
				Long chargeId = item.getChargeId();
				if (null != chargeId) {
					carriageDao.setAsPaied(chargeId);
				}
			} else if (type.equals(Constants.CEREMONY)) {
				ceremonyDao.setAsPaied(item.getChargeId());
			} else if (type.equals(Constants.CREMATION_HIST)) {
				cremationHistDao.setAsPaied(item.getChargeId());
			} else if (type.equals(Constants.FREEZER_RENT)) {
				freezerDao.setAsPaied(item.getChargeId());
			} else if (type.equals(Constants.HALL_RENT)) {
				hallRentDao.setAsPaied(item.getChargeId());
			}
		}
	}

	@Transactional(readOnly = true)
	public ChargeRecord getOne(Long id) {
		try {
			//			ChargeRecord record = chargeRecordDao.get(id);
			//			ChargeRecord target = new ChargeRecord();
			//			BeanUtils.copyProperties(record, target);

			ChargeRecord findUnique = chargeRecordDao.findUnique("from ChargeRecord where id=?", id);
			chargeRecordDao.initProxyObject(findUnique.getItems());
			return findUnique;
			//			return target;
		} catch (ObjectNotFoundException e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("发生异常!");
		}
	}

	public void del(Long... ids) {
		Transaction tx = chargeRecordDao.getSession().beginTransaction();
		try {
			for (Long id : ids) {
				ChargeRecord entity = getOne(id);
				if (getOne(id) == null) {
					continue;
				}

				Registration reg = entity.getRegistration();
				String flowNo = entity.getId() + "-" + reg.getBizNo();
				deleteStorageHistRecord(flowNo);

				chargeRecordDao.delete(id);

			}
			tx.commit();
		} catch (Exception e) {
			tx.rollback();
			logger.error(e.getMessage(), e);
			throw new BusinessException("发生异常!");
		}
	}

	private void deleteStorageHistRecord(String flowNo) {
		SaleHist findUniqueBy = saleHistDao.findUniqueBy("flowNo", flowNo);
		if (findUniqueBy != null) {
			long saleFlowId = findUniqueBy.getId();
			saleMananger.delSale(saleFlowId);
		}
	}

	//	private boolean notExist(Long id) {
	//		return getOne(id) == null;
	//	}

	@Transactional(readOnly = true)
	public Page<ChargeRecordListItem> search(Page<ChargeRecord> cPage, ChargeRecordCriteria criteria) {
		try {
			chargeRecordDao.search(cPage, criteria);
			List<ChargeRecord> resultList = cPage.getResult();

			Page<ChargeRecordListItem> resultPage = new Page<ChargeRecordListItem>();
			for (ChargeRecord chargeRecord : resultList) {
				ChargeRecordListItem item = new ChargeRecordListItem();
				item.setChargeDate(chargeRecord.getChargeDate());
				item.setId(chargeRecord.getId());
				item.setOperator(chargeRecord.getOperator());
				item.setPaidFee(chargeRecord.getPaidFee());
				item.setShouldPaidTotalFee(chargeRecord.getShouldPaidTotalFee());
				item.setTotalFee(chargeRecord.getTotalFee());
				item.setBizNo(chargeRecord.getRegistration().getBizNo());
				item.setDeadName(chargeRecord.getRegistration().getDeadName());
				resultPage.getResult().add(item);
			}
			resultPage.setAutoCount(cPage.isAutoCount());
			resultPage.setOrder(cPage.getOrder());
			resultPage.setOrderBy(cPage.getOrderBy());
			resultPage.setPageNo(cPage.getPageNo());
			resultPage.setPageSize(cPage.getPageSize());
			resultPage.setTotalCount(cPage.getTotalCount());
			return resultPage;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("发生异常!");
		}
	}

	public static void main(String[] args) throws SQLException {
		Driver driver = new Driver();
		Properties p = new Properties();
		p.setProperty("user", "root");
		p.setProperty("password", "root21");
		Properties p2 = new Properties();
		p2.setProperty("user", "root");
		p2.setProperty("password", "root21");
		Connection connect = driver.connect("jdbc:mysql://localhost:3306/emet", p);
		Statement createStatement = connect.createStatement();
		connect = driver.connect("jdbc:mysql://localhost:3306/emet", p2);
		createStatement = connect.createStatement();
	}
}
